package com.jamie.date;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.Calendar;
import java.util.Date;
import java.util.Objects;

/**
 * jamie时间工具类
 * @author jamie
 * @date 2020/7/30 16:22
 */
@SuppressWarnings("all")
public class DateUtils extends org.apache.commons.lang3.time.DateUtils {
    private DateUtils() { }

    public static final String TIME_FORMATTER_STR = "HH:mm:ss";
    public static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern(TIME_FORMATTER_STR);

    public static final String DATE_FORMATTER_STR = "yyyy-MM-dd";
    public static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern(DATE_FORMATTER_STR);

    public static final String DATETIME_FORMATTER_STR = "yyyy-MM-dd HH:mm:ss";
    public static final DateTimeFormatter DATETIME_FORMATTER = DateTimeFormatter.ofPattern(DATETIME_FORMATTER_STR);

    /** parsePatterns */
    private static final String[] PARSE_PATTERNS = {"yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM",
            "yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM", "yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss",
            "yyyy.MM.dd HH:mm", "yyyy.MM", "yyyyMMddHHmmss", "yyyyMMdd"};
    /***/
    public static String CRON_DATE = "ss mm HH dd MM ? yyyy";

    /** 每日定时任务表达式 */
    public static String DAILY_CRON_EXPRESSION = "ss mm HH * * ? *";

    /**
     * 获取当前系统时间
     */
    public static Date getDate() {
        return new Date();
    }

    /**
     * 获取当前系统时间
     */
    public static LocalTime getLocalTime() {
        return LocalTime.now();
    }

    /**
     * 获取当前系统日期
     */
    public static LocalDate getLocalDate() {
        return LocalDate.now();
    }

    /**
     * 获取当前系统日期时间
     */
    public static LocalDateTime getLocalDateTime() {
        return LocalDateTime.now();
    }

    /**
     * 获取当前系统时间字符串(返回格式为 HH:mm:ss)
     */
    public static String getLocalTimeStr() {
        return LocalTime.now().format(TIME_FORMATTER);
    }

    /**
     * 获取当前系统日期字符串(返回格式为 yyyy-MM-dd)
     */
    public static String getLocalDateStr() {
        return LocalDate.now().format(DATE_FORMATTER);
    }

    /**
     * 获取当前系统日期时间字符串(返回格式为 yyyy-MM-dd HH:mm:ss)
     */
    public static String getLocalDateTimeStr() {
        return LocalDateTime.now().format(DATETIME_FORMATTER);
    }

    /**
     * 字符串转LocalTime
     * @param time 时间字符串(格式为 HH:mm:ss)
     */
    public static LocalTime str2LocalTime(String time) {
        return LocalTime.parse(time, TIME_FORMATTER);
    }

    /**
     * 字符串转LocalDate
     * @param date 时间字符串(格式为 yyyy-MM-dd)
     */
    public static LocalDate str2LocalDate(String date) {
        return LocalDate.parse(date, DATE_FORMATTER);
    }

    /**
     * 字符串转LocalDateTime
     * @param dateTime 时间字符串(格式为 yyyy-MM-dd HH:mm:ss)
     */
    public static LocalDateTime str2LocalDateTime(String dateTime) {
        return LocalDateTime.parse(dateTime, DATETIME_FORMATTER);
    }

    /**
     * Date转LocalDateTime
     * @param date Data 对象
     */
    public static LocalDateTime date2LocalDateTime(Date date) {
        int year = getYear(date);
        int monthValue = getMonth(date);
        int day = getDay(date);
        int hour = getHour(date);
        int minute = getMinute(date);
        int second = getSecond(date);
        return LocalDateTime.of(year, monthValue, day, hour, minute, second);
    }

    /**
     * Date转LocalDate
     * @param date Data 对象
     */
    public static LocalDate date2LocalDate(Date date) {
        int year = getYear(date);
        int monthValue = getMonth(date);
        int day = getDay(date);
        return LocalDate.of(year, monthValue, day);
    }

    /**
     * Date转LocalDate
     * @param date Data 对象
     */
    public static LocalTime date2LocalTime(Date date) {
        int hour = getHour(date);
        int minute = getMinute(date);
        int second = getSecond(date);
        return LocalTime.of(hour, minute, second);
    }

    /**
     * LocalDateTime转换为Date
     * @param localDateTime 日期+时间对象
     */
    public static Date localDateTime2Date(LocalDateTime localDateTime) {
        String year = getYear(localDateTime);
        String monthValue = getMonth(localDateTime);
        String day = getDay(localDateTime);
        String hour = getHour(localDateTime);
        String minute = getMinute(localDateTime);
        String second = getSecond(localDateTime);
        return str2Date(year + monthValue + day + hour + minute + second, "yyyyMMddHHmmss");
    }

    /**
     * 时间戳转换字符串格式时间
     * @param time    时间戳
     * @param pattern 默认 yyyy-MM-dd HH:mm:ss
     */
    public static String timestamp2Str(Long time, String pattern) {
        if (time == null || time == 0) {
            return null;
        }
        if (StringUtils.isEmpty(pattern)) {
            pattern = "yyyy-MM-dd HH:mm:ss";
        }
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern);
        return simpleDateFormat.format(new Date(time));
    }

    /**
     * 获取年份
     * @param localDateTime LocalDateTime时间对象
     */
    public static String getYear(LocalDateTime localDateTime) {
        return format(localDateTime.getYear());
    }

    /**
     * 获取年份
     * @param date Date时间对象
     */
    public static int getYear(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.get(Calendar.YEAR);
    }

    /**
     * 获取月份
     * @param localDateTime LocalDateTime时间对象
     */
    public static String getMonth(LocalDateTime localDateTime) {
        return format(localDateTime.getMonthValue());
    }

    /**
     * 获取月份
     * @param date Date时间对象
     */
    public static int getMonth(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.get(Calendar.MONTH) + 1;
    }

    /**
     * 获取日期
     * @param localDateTime LocalDateTime时间对象
     */
    public static String getDay(LocalDateTime localDateTime) {
        return format(localDateTime.getDayOfMonth());
    }

    /**
     * 获取日期
     * @param date Date时间对象
     */
    public static int getDay(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.get(Calendar.DATE);
    }

    /**
     * 获取小时数
     * @param localDateTime LocalDateTime时间对象
     */
    public static String getHour(LocalDateTime localDateTime) {
        return format(localDateTime.getHour());
    }

    /**
     * 获取小时数
     * @param date Date时间对象
     */
    public static int getHour(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.get(Calendar.HOUR_OF_DAY);
    }

    /**
     * 获取分钟数
     * @param localDateTime LocalDateTime时间对象
     */
    public static String getMinute(LocalDateTime localDateTime) {
        return format(localDateTime.getMinute());
    }

    /**
     * 获取分钟数
     * @param date Date时间对象
     */
    public static int getMinute(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.get(Calendar.MINUTE);
    }

    /**
     * 获取秒数
     * @param localDateTime LocalDateTime时间对象
     */
    public static String getSecond(LocalDateTime localDateTime) {
        return format(localDateTime.getSecond());
    }

    /**
     * 获取秒数
     * @param date Date时间对象
     */
    public static int getSecond(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.get(Calendar.SECOND);
    }

    /**
     * 数据值字符串格式化，低于10前面补0
     * @param number 数据值
     */
    public static String format(int number) {
        String num = String.valueOf(number);
        return number < 10 ? "0" + num : num;
    }

    /**
     * 判断字符串日期是否匹配指定的格式化日期
     * @param strDate   时间字符串
     * @param formatter 日期格式
     */
    public static boolean isValidDate(String strDate, String formatter) {
        ParsePosition pos = new ParsePosition(0);
        if (strDate == null || "".equals(strDate) || formatter == null || "".equals(formatter)) {
            return false;
        }
        try {
            SimpleDateFormat sdf = new SimpleDateFormat(formatter);
            sdf.setLenient(false);
            Date date = sdf.parse(strDate, pos);
            if (date == null) {
                return false;
            } else {
                return pos.getIndex() <= sdf.format(date).length();
            }
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 字符串转时间
     * @param strDate 时间字符串
     * @param format  编码格式
     */
    public static Date str2Date(String strDate, String format) {
        if (strDate == null) {
            return null;
        }
        DateFormat df;
        try {
            if (format == null) {
                df = new SimpleDateFormat();
            } else {
                df = new SimpleDateFormat(format);
            }
            df.setLenient(false);
            return df.parse(strDate);
        } catch (ParseException e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 字符串转时间
     * @param strDate 时间字符串
     */
    public static Date str2Date(String strDate) {
        if (strDate == null) {
            return null;
        }
        try {
            return parseDate(strDate, PARSE_PATTERNS);
        } catch (ParseException e) {
            return null;
        }
    }

    /**
     * 获取当天0点时间
     */
    public static Date getTodayZero() {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        return calendar.getTime();
    }

    /**
     * 获取明天0点时间
     */
    public static Date getTomorrowZero() {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        calendar.add(calendar.DATE, 1);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        return calendar.getTime();
    }

    /**
     * 校验入参是否为空
     * @param date1
     * @param date2
     * @return
     */
    public static Boolean checkDate(Date date1, Date date2) {
        if (Objects.isNull(date1) || Objects.isNull(date2)) {
            return false;
        }
        return true;
    }

    /**
     * 比较入参大小，true date1小于date2, false date1大于date2
     * @param date1
     * @param date2
     * @return
     */
    public static Boolean compareTo(Date date1, Date date2) {
        if (!checkDate(date1, date2)) {
            return false;
        }
        if (date1.compareTo(date2) == 1) {
            return false;
        }
        return true;
    }

    /**
     * 日期转换cron表达式
     * @param date
     * @return
     */
    public static String getCron(Date date) {
        return DateFormatUtils.format(date, CRON_DATE);
    }

    /**
     * 日期转换为每日执行的cron表达式
     * @param time
     * @return
     */
    public static String getDailyCron(LocalTime time) {
        return time.format(DateTimeFormatter.ofPattern(DAILY_CRON_EXPRESSION));
    }

    /**
     * 计算两个时间相差天数，按毫秒计算，不满24小时不算1天
     * @param date1 开始时间
     * @param date2 结束时间
     */
    public static int days(Date date1, Date date2) {
        return (int) ((date2.getTime() - date1.getTime()) / (1000 * 3600 * 24));
    }

    /**
     * 计算两个时间相差天数，按毫秒计算，不满24小时不算1天
     * @param timeStampStart 开始时间戳
     * @param timeStampEnd   结束时间戳
     */
    public static int days(long timeStampStart, long timeStampEnd) {
        return (int) ((timeStampEnd - timeStampStart) / (1000 * 3600 * 24));
    }
}
